/** demoks 的系统库
 *  
 */
#include "include.h"

static const char *TAG = "demoks_system";
static nvs_handle handle;

esp_err_t CHECK_DEMOKS_SYSTEM(char *tag, esp_err_t t)
{
    switch (t)
    {
    case ESP_OK:
        ESP_LOGI(TAG, "[%s] ESP_ERR_NVS_INVALID_HANDLE", tag);
        break;
    case ESP_ERR_NVS_INVALID_HANDLE:
        ESP_LOGW(TAG, "[%s] ESP_ERR_NVS_INVALID_HANDLE", tag);
        break;
    case ESP_ERR_NVS_READ_ONLY:
        ESP_LOGW(TAG, "[%s] ESP_ERR_NVS_READ_ONLY", tag);
        break;
    case ESP_ERR_NVS_INVALID_NAME:
        ESP_LOGW(TAG, "[%s] ESP_ERR_NVS_INVALID_NAME", tag);
        break;
    case ESP_ERR_NVS_NOT_ENOUGH_SPACE:
        ESP_LOGW(TAG, "[%s] ESP_ERR_NVS_NOT_ENOUGH_SPACE", tag);
        break;
    case ESP_ERR_NVS_REMOVE_FAILED:
        ESP_LOGW(TAG, "[%s] ESP_ERR_NVS_REMOVE_FAILED", tag);
        break;
    case ESP_ERR_NVS_VALUE_TOO_LONG:
        ESP_LOGW(TAG, "[%s] ESP_ERR_NVS_VALUE_TOO_LONG", tag);
        break;
    default:
        ESP_LOGW(TAG, "[%s] unknown error", tag);
        break;
    }
    return t;
}

demoks_system_mode_t get_system_mode()
{
    uint8_t mode = 0;
    esp_err_t result = 0;
    result = nvs_get_u8(handle, "_system_mode", &mode);
    if (ESP_OK != result)
    {
        CHECK_DEMOKS_SYSTEM("get_system_mode", result);
        mode = DEMOKS_SYSTEM_REGULAR_MODE;
    }
    return (demoks_system_mode_t)mode;
}

esp_err_t set_system_mode(demoks_system_mode_t s)
{
    esp_err_t result = 0;
    result = nvs_set_u8(handle, "_system_mode", s);
    if (ESP_OK != result)
        CHECK_DEMOKS_SYSTEM("set_system_mode", result);
    return result;
}

char *demoks_system_set_public_key()
{
    static char key[DEMOKS_SYSTEM_PUBLIC_KEY_LEN * 2];
    esp_err_t result = 0;
    uint8_t *data;
    data = malloc(DEMOKS_SYSTEM_PUBLIC_KEY_LEN / 2);
    esp_fill_random(data, DEMOKS_SYSTEM_PUBLIC_KEY_LEN / 2);
    array_to_hex_str(data, DEMOKS_SYSTEM_PUBLIC_KEY_LEN / 2, &key);
    result = nvs_set_str(handle, "_p_key", key);
    if (ESP_OK != result)
        CHECK_DEMOKS_SYSTEM("set_public_key", result);
    free(data);
    return key;
}

char *demoks_system_get_public_key()
{
    static char key[DEMOKS_SYSTEM_PUBLIC_KEY_LEN * 2];
    esp_err_t result = 0;
    size_t len = DEMOKS_SYSTEM_PUBLIC_KEY_LEN * 2;
    result = nvs_get_str(handle, "_p_key", key, &len);
    if (ESP_OK != result)
    {
        CHECK_DEMOKS_SYSTEM("get_public_key", result);
        return demoks_system_set_public_key();
    }
    return key;
}

esp_err_t demoks_system_get_device_id(char *device_id)
{
    uint8_t mac[6];
    char str[12];
    esp_efuse_mac_get_default(mac);
    array_to_hex_str(mac, 6, &str);
    for (int i = 0; i < 12; i++)
        device_id[i] = str[i];
    return ESP_OK;
}

esp_err_t demoks_system_set_wifi_ssid_passwd(char ssid[32], char passwd[32])
{
    esp_err_t result = 0;
    result = nvs_set_str(handle, "_ssid", ssid);
    if (ESP_OK != result)
        CHECK_DEMOKS_SYSTEM("set_wifi_ssid_passwd", result);
    result = nvs_set_str(handle, "_passwd", passwd);
    if (ESP_OK != result)
        CHECK_DEMOKS_SYSTEM("set_wifi_ssid_passwd", result);
    return result;
}

esp_err_t demoks_system_get_wifi_ssid_passwd(char *ssid, char *passwd)
{
    esp_err_t result = 0;
    size_t len = 32;
    result = nvs_get_str(handle, "_ssid", ssid, &len);
    if (ESP_OK != result)
        CHECK_DEMOKS_SYSTEM("get_wifi_ssid_passwd", result);
    len = 32;
    result = nvs_get_str(handle, "_passwd", passwd, &len);
    if (ESP_OK != result)
        CHECK_DEMOKS_SYSTEM("get_wifi_ssid_passwd", result);
    return result;
}

uint8_t get_access_net_count()
{
    uint8_t count = 0;
    esp_err_t result = 0;
    result = nvs_get_u8(handle, DEMOKS_SYSTEM_KEY_ACCESS_NET_COUNT, &count);
    if (ESP_OK != result)
    {
        CHECK_DEMOKS_SYSTEM("get_access_net_count", result);
        count = 0;
    }
    return (uint8_t)count;
}

esp_err_t access_net_count_pp()
{
    esp_err_t result = 0;
    uint8_t count = get_access_net_count();
    count++;
    result = nvs_set_u8(handle, DEMOKS_SYSTEM_KEY_ACCESS_NET_COUNT, count);
    if (ESP_OK != result)
        CHECK_DEMOKS_SYSTEM("access_net_count_pp", result);
    return result;
}

esp_err_t access_net_count_clear()
{
    esp_err_t result = 0;
    uint8_t count = 0;
    result = nvs_set_u8(handle, DEMOKS_SYSTEM_KEY_ACCESS_NET_COUNT, count);
    if (ESP_OK != result)
        CHECK_DEMOKS_SYSTEM("access_net_count_clear", result);
    return result;
}

void demoks_system_restart()
{
    fflush(stdout);
    esp_restart();
}

esp_err_t demoks_system_init()
{
    return nvs_open("demoks_system", NVS_READWRITE, &handle);
}